package com.xiye.system.controller.login;

import com.xiye.common.controller.BaseController;
import com.xiye.common.entity.*;
import com.xiye.common.session.redis.impl.RedisManager;
import com.xiye.common.util.*;
import com.xiye.system.config.YmlConfig;
import com.xiye.system.service.button.ButtonService;
import com.xiye.system.service.buttonrights.ButtonrightsService;
import com.xiye.system.service.department.DepartmentService;
import com.xiye.system.service.menu.MenuService;
import com.xiye.system.service.role.RoleService;
import com.xiye.system.service.user.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * @Package com.xiye.system.controller.login
 * @Description 请求登录，验证用户
 * @Author 西野
 * @Date 2018-07-12
 * @Version V1.0
 */
@RestController
@RequestMapping("/login")
@Api(value = "/login", tags = "登录/退出")
public class LoginController extends BaseController {

    @Autowired
    private UserService userService;
    @Autowired
    private DepartmentService departmentService;
    @Autowired
    private MenuService menuService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private ButtonService buttonService;
    @Autowired
    private ButtonrightsService buttonrightsService;
    @Autowired
    private YmlConfig ymlConfig;
    @Autowired
    private RedisManager redisManager;

    /*
     * @Author 西野
     * @Date 2018-08-08 14:56:35
     * @Description 用户登录
     * @Param []
     * @Return java.lang.Object
     */
    @ApiOperation(value = "用户登录", notes = "通过用户名和密码进行登录")
    @ApiImplicitParams({@ApiImplicitParam(name = "USERNAME", value = "登录名", required = true), @ApiImplicitParam(name = "PASSWORD", value = "密码", required = true)})
    @RequestMapping(value = "/login_toLogin", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
    public Result login() throws Exception {
        PageData pd = this.getPageData();
        Session session = Jurisdiction.getSession();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("success", true);
        String passwd = new SimpleHash("SHA-1", pd.getString("USERNAME"), pd.getString("PASSWORD")).toString(); // 密码加密
        passwd = "d0d0bbda3e896876fdedbb8c973b81dcc2005ed8";
        pd.put("PASSWORD", passwd);
        String errInfo = "";
        pd = userService.getUserByNameAndPwd(pd); // 根据用户名和密码去读取用户信息
        User user = new User();
        if (pd != null) {
            this.removeSession(pd.getString("USERNAME"));// 清理缓存
            user.setUSER_ID(pd.getString("USER_ID"));
            map.put("USER_ID", pd.getString("USER_ID"));
            user.setUSERNAME(pd.getString("USERNAME"));
            map.put("USERNAME", pd.getString("USERNAME"));
            user.setPASSWORD(pd.getString("PASSWORD"));
            map.put("PASSWORD", pd.getString("PASSWORD"));
            user.setNAME(pd.getString("NAME"));
            map.put("NAME", pd.getString("NAME"));
            user.setRIGHTS(pd.getString("RIGHTS"));
            map.put("RIGHTS", pd.getString("RIGHTS"));
            user.setROLE_ID(pd.getString("ROLE_ID"));
            map.put("ROLE_ID", pd.getString("ROLE_ID"));
            user.setLAST_LOGIN(pd.getString("LAST_LOGIN"));
            map.put("LAST_LOGIN", pd.getString("LAST_LOGIN"));
            user.setRNUMBER(pd.getString("RNUMBER"));
            map.put("RNUMBER", pd.getString("RNUMBER"));
            user.setDEPARTMENT_ID(pd.getString("DEPARTMENT_ID"));
            map.put("DEPARTMENT_ID", pd.getString("DEPARTMENT_ID"));
            user.setDEPARTMENT_NAME(pd.getString("DEPARTMENT_NAME"));
            map.put("DEPARTMENT_NAME", pd.getString("DEPARTMENT_NAME"));
            user.setIP(pd.getString("IP"));
            map.put("IP", pd.getString("IP"));
            user.setSTATUS(pd.getString("STATUS"));
            map.put("STATUS", pd.getString("STATUS"));
            session.setAttribute(Const.SESSION_USER, user); // 把用户信息放session中
            //session.removeAttribute(Const.SESSION_SECURITY_CODE); // 清除登录验证码的session
            // shiro加入身份验证
            Subject subject = SecurityUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(pd.getString("USERNAME"), pd.getString("PASSWORD"));
            try {
                //token.setRememberMe(true);
                subject.login(token);
            } catch (AuthenticationException e) {
                errInfo = "身份验证失败！";
                map.put("success", false);
            }
        } else {
            errInfo = "用户名或密码错误"; // 用户名或密码有误
        }
        if (Tools.isEmpty(errInfo)) {
            errInfo = "验证成功"; // 验证成功
            map.put("success", true);
        }
        /*map.put("result", errInfo);*/
        map.put("msg", errInfo);
        return ResultUtil.setRowbackResut_entity(true, 200, errInfo, JSONObject.fromObject(map));
    }

    /*
     * @Author 西野
     * @Date 2018-06-22 10:06:06
     * @Description 用户注销或退出登录
     * @Param []
     * @Return ModelAndView
     */
    @ApiOperation(value = "用户退出", notes = "退出登录注销用户登录信息")
    @RequestMapping(value = "/logout", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
    public Result logout() {
        Subject subject = SecurityUtils.getSubject();
        Map<String, Object> map = new HashMap<String, Object>();
        PageData pd = this.getPageData();
        /*String USERNAME = Jurisdiction.getUsername();
        String key = "menu_user:" + USERNAME;
        if (redisManager.get(key) != null) {
            redisManager.del(key);
        }*/
        subject.logout(); // shiro销毁登录
        pd.put("msg", pd.getString("msg"));
        return ResultUtil.setRowbackResut_entity(true, 200, ymlConfig.getServer_success(), map);
    }

    /*
     * @Author 西野
     * @Date 2018-06-22 10:06:06
     * @Description 访问系统首页
     * @Param [changeMenu]
     * @Return ModelAndView
     */
    @ApiOperation(value = "缓存信息", notes = "登录后缓存信息")
    @RequestMapping(value = "/index/{changeMenu}", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
    public Result login_index(@PathVariable("changeMenu") String changeMenu) {
        Map<String, Object> map = new HashMap<String, Object>();
        JSONObject jsonObject = new JSONObject();
        try {
            Session session = Jurisdiction.getSession();
            User user = Jurisdiction.getUser(Const.SESSION_USER); // 读取session中的用户信息(单独用户信息)
            if (user != null) {
                String USERNAME = user.getUSERNAME();
                String key = "menu_user:" + USERNAME;
                if (redisManager.get(key) == null) {
                    User userr = Jurisdiction.getUser(Const.SESSION_USERROL); // 读取session中的用户信息(含角色信息)
                    if (null == userr) {
                        user = userService.getUserAndRoleById(user.getUSER_ID()); // 通过用户ID读取用户信息和角色信息
                        session.setAttribute(Const.SESSION_USERROL, user); // 存入session
                    } else {
                        user = userr;
                    }
                    Role role = user.getRole(); // 获取用户角色
                    String roleRights = role != null ? role.getRIGHTS() : ""; // 角色权限(菜单权限)
                    String ROLE_IDS = user.getROLE_IDS();
                    session.setAttribute(USERNAME + Const.SESSION_ROLE_RIGHTS, roleRights); // 将角色权限存入session
                    jsonObject.put("roleRights", roleRights);
                    session.setAttribute(Const.SESSION_USERNAME, USERNAME); // 放入用户名到session
                    session.setAttribute(Const.SESSION_U_NAME, user.getNAME()); // 放入用户姓名到session
                    this.setAttributeToAllDEPARTMENT_ID(session, USERNAME); // 把用户的组织机构权限放到session里面
                    List<Menu> allmenuList = this.getAttributeMenu(session, USERNAME, roleRights, getArrayRoleRights(ROLE_IDS)); // 菜单缓存
                    Map<String, String> getUQX = new HashMap<String, String>();
                    Map<String, List<String>> getUQX2 = new HashMap<String, List<String>>();
                    if (null == session.getAttribute(USERNAME + Const.SESSION_QX)) {
                        getUQX = this.getUQX(USERNAME);
                        getUQX2 = this.getUQX2(USERNAME);
                        session.setAttribute(USERNAME + Const.SESSION_QX, getUQX); // 主职角色按钮权限放到session中
                        session.setAttribute(USERNAME + Const.SESSION_QX2, getUQX2); // 副职角色按钮权限放到session中
                        jsonObject.put("getUQX", JSONObject.fromObject(getUQX));
                        jsonObject.put("getUQX2", JSONObject.fromObject(getUQX2));
                    }
                    jsonObject.put("USER", JSONObject.fromObject(user));
                    jsonObject.put("menuList", JSONArray.fromObject(allmenuList));
                    map.put("USER", JSONObject.fromObject(user));
                    map.put("menuList", JSONArray.fromObject(allmenuList));
                    redisManager.set(key, jsonObject.toString());
                } else {
                    jsonObject = JSONObject.fromObject(redisManager.get(key));
                    map.put("USER", jsonObject.get("USER"));
                    map.put("menuList", jsonObject.get("menuList"));
                    session.setAttribute(Const.SESSION_USERROL, jsonObject.get("USER")); // 存入session
                    session.setAttribute(USERNAME + Const.SESSION_ROLE_RIGHTS, jsonObject.get("roleRights")); // 将角色权限存入session
                    session.setAttribute(Const.SESSION_USERNAME, USERNAME); // 放入用户名到session
                    session.setAttribute(Const.SESSION_U_NAME, user.getNAME()); // 放入用户姓名到session
                    session.setAttribute(USERNAME + Const.SESSION_QX, jsonObject.get("getUQX")); // 主职角色按钮权限放到session中
                    session.setAttribute(USERNAME + Const.SESSION_QX2, jsonObject.get("getUQX2")); // 副职角色按钮权限放到session中
                    session.setAttribute(USERNAME + Const.SESSION_ALLMENULIST, jsonObject.get("menuList"));
                }
                return ResultUtil.setRowbackResut_entity(true, 200, ymlConfig.getServer_success(), map);
            } else {
                return ResultUtil.setRowbackResut_entity(false, 401, ymlConfig.getLogin_again(), map);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return ResultUtil.setRowbackResut_entity(false, 500, ymlConfig.getServer_error(), map);
        }

    }

    /*
     * @Author 西野
     * @Date 2018-06-22 10:06:06
     * @Description 把用户的组织机构权限放到session里面
     * @Param [session, USERNAME]
     * @Return void
     */
    public void setAttributeToAllDEPARTMENT_ID(Session session, String USERNAME) throws Exception {
        String DEPARTMENT_IDS = "0", DEPARTMENT_ID = "0";
        if (!"admin".equals(USERNAME)) {
            PageData pd = departmentService.getDEPARTMENT_IDS(USERNAME);
            DEPARTMENT_IDS = null == pd ? "无权" : pd.getString("DEPARTMENT_IDS");
            DEPARTMENT_ID = null == pd ? "无权" : pd.getString("DEPARTMENT_ID");
        }
        session.setAttribute(Const.DEPARTMENT_IDS, DEPARTMENT_IDS); // 把用户的组织机构权限集合放到session里面
        session.setAttribute(Const.DEPARTMENT_ID, DEPARTMENT_ID); // 把用户的最高组织机构权限放到session里面
    }

    /*
     * @Author 西野
     * @Date 2018-06-22 11:06:06
     * @Description 菜单缓存
     * @Param [session, USERNAME, roleRights, arrayRoleRights]
     * @Return List<Menu>
     */
    public List<Menu> getAttributeMenu(Session session, String USERNAME, String roleRights, List<String> arrayRoleRights) throws Exception {
        List<Menu> allmenuList = new ArrayList<Menu>();
        if (null == session.getAttribute(USERNAME + Const.SESSION_ALLMENULIST)) {
            allmenuList = menuService.listAllMenuQx("0"); // 获取所有菜单
            if (Tools.notEmpty(roleRights)) {
                allmenuList = this.readMenu(allmenuList, roleRights, arrayRoleRights); // 根据角色权限获取本权限的菜单列表
            }
            session.setAttribute(USERNAME + Const.SESSION_ALLMENULIST, allmenuList);// 菜单权限放入session中
        } else {
            allmenuList = (List<Menu>) session.getAttribute(USERNAME + Const.SESSION_ALLMENULIST);
        }
        return allmenuList;
    }

    /*
     * @Author 西野
     * @Date 2018-06-22 11:06:06
     * @Description 获取副职角色权限List
     * @Param [ROLE_IDS]
     * @Return java.util.List<java.lang.String>
     */
    public List<String> getArrayRoleRights(String ROLE_IDS) {
        if (Tools.notEmpty(ROLE_IDS)) {
            List<String> list = new ArrayList<String>();
            String arryROLE_ID[] = ROLE_IDS.split(",xiye,");
            List<String> rolelist = Arrays.asList(arryROLE_ID);
            rolelist.forEach(r -> {
                PageData pd = new PageData();
                pd.put("ROLE_ID", r);
                try {
                    pd = roleService.findObjectById(pd);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (null != pd) {
                    String RIGHTS = pd.getString("RIGHTS");
                    if (Tools.notEmpty(RIGHTS)) {
                        list.add(RIGHTS);
                    }
                }
            });
            return list.size() == 0 ? null : list;
        } else {
            return null;
        }
    }

    /*
     * @Author 西野
     * @Date 2018-06-22 11:06:06
     * @Description 根据角色权限获取本权限的菜单列表(递归处理)
     * @Param [menuList, roleRights, arrayRoleRights]
     * @Return java.util.List<com.xiye.common.entity.Menu>
     */
    public List<Menu> readMenu(List<Menu> menuList, String roleRights, List<String> arrayRoleRights) {
        menuList.forEach(m -> {
            Boolean b1 = RightsHelper.testRights(roleRights, m.getMENU_ID());
            m.setHasMenu(b1); // 赋予主职角色菜单权限
            if (!b1 && null != arrayRoleRights) {
                arrayRoleRights.forEach(r -> {
                    if (RightsHelper.testRights(r, m.getMENU_ID())) {
                        m.setHasMenu(true);
                        return;
                    }
                });
            }
            if (m.isHasMenu()) { // 判断是否有此菜单权限
                this.readMenu(m.getSubMenu(), roleRights, arrayRoleRights);// 是：继续排查其子菜单
            }

        });
        return menuList;
    }

    /*
     * @Author 西野
     * @Date 2018-06-22 12:06:06
     * @Description 获取用户权限
     * @Param [USERNAME]
     * @Return java.util.Map<java.lang.String,java.lang.String>
     */
    public Map<String, String> getUQX(String USERNAME) {
        PageData pd = new PageData();
        Map<String, String> map = new HashMap<String, String>();
        try {
            pd.put(Const.SESSION_USERNAME, USERNAME);
            PageData userpd = userService.findByUsername(pd); // 通过用户名获取用户信息
            String ROLE_ID = userpd.get("ROLE_ID").toString();
            String ROLE_IDS = userpd.getString("ROLE_IDS");
            pd.put("ROLE_ID", ROLE_ID); // 获取角色ID
            pd = roleService.findObjectById(pd); // 获取角色信息
            map.put("adds", pd.getString("ADD_QX")); // 增
            map.put("dels", pd.getString("DEL_QX")); // 删
            map.put("edits", pd.getString("EDIT_QX")); // 改
            map.put("chas", pd.getString("CHA_QX")); // 查
            List<PageData> buttonQXnamelist = new ArrayList<PageData>();
            if ("admin".equals(USERNAME)) {
                buttonQXnamelist = buttonService.listAll(pd); // admin用户拥有所有按钮权限
            } else {
                if (Tools.notEmpty(ROLE_IDS)) {// (主副职角色综合按钮权限)
                    ROLE_IDS = ROLE_IDS + ROLE_ID;
                    String arryROLE_ID[] = ROLE_IDS.split(",xiye,");
                    buttonQXnamelist = buttonrightsService.listAllBrAndQxnameByZF(arryROLE_ID);
                } else { // (主职角色按钮权限)
                    buttonQXnamelist = buttonrightsService.listAllBrAndQxname(pd); // 此角色拥有的按钮权限标识列表
                }
            }
            for (int i = 0; i < buttonQXnamelist.size(); i++) {
                map.put(buttonQXnamelist.get(i).getString("QX_NAME"), "1"); // 按钮权限
            }
        } catch (Exception e) {
            logger.error(e.toString(), e);
        }
        return map;
    }

    /*
     * @Author 西野
     * @Date 2018-06-22 12:06:06
     * @Description 获取用户权限(处理副职角色)
     * @Param [USERNAME]
     * @Return java.util.Map<java.lang.String,java.util.List<java.lang.String>>
     */
    public Map<String, List<String>> getUQX2(String USERNAME) throws Exception {
        PageData pd = new PageData();
        Map<String, List<String>> maps = new HashMap<String, List<String>>();
        pd.put(Const.SESSION_USERNAME, USERNAME);
        PageData userpd = userService.findByUsername(pd); // 通过用户名获取用户信息
        String ROLE_IDS = userpd.getString("ROLE_IDS");
        if (Tools.notEmpty(ROLE_IDS)) {
            String arryROLE_ID[] = ROLE_IDS.split(",xiye,");
            List<String> rolelist = Arrays.asList(arryROLE_ID);
            List<String> addsList = new ArrayList<String>();
            List<String> delsList = new ArrayList<String>();
            List<String> editsList = new ArrayList<String>();
            List<String> chasList = new ArrayList<String>();
            rolelist.forEach(r -> {
                PageData rolePd = new PageData();
                rolePd.put("ROLE_ID", r);
                try {
                    rolePd = roleService.findObjectById(rolePd);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                addsList.add(rolePd.getString("ADD_QX"));
                delsList.add(rolePd.getString("DEL_QX"));
                editsList.add(rolePd.getString("EDIT_QX"));
                chasList.add(rolePd.getString("CHA_QX"));
            });
            maps.put("addsList", addsList); // 增
            maps.put("delsList", delsList); // 删
            maps.put("editsList", editsList); // 改
            maps.put("chasList", chasList); // 查
        }

        return maps;
    }

    /*
     * @Author 西野
     * @Date 2018-06-22 09:06:06
     * @Description 清理session
     * @Param [USERNAME]
     * @Return void
     */
    public void removeSession(String USERNAME) {
        Session session = Jurisdiction.getSession(); // 以下清除session缓存
        session.removeAttribute(Const.SESSION_USER);
        session.removeAttribute(USERNAME + Const.SESSION_ROLE_RIGHTS);
        session.removeAttribute(USERNAME + Const.SESSION_ALLMENULIST);
        session.removeAttribute(USERNAME + Const.SESSION_MENULIST);
        session.removeAttribute(USERNAME + Const.SESSION_QX);
        session.removeAttribute(USERNAME + Const.SESSION_QX2);
        session.removeAttribute(Const.SESSION_USERPDS);
        session.removeAttribute(Const.SESSION_USERNAME);
        session.removeAttribute(Const.SESSION_U_NAME);
        session.removeAttribute(Const.SESSION_USERROL);
        session.removeAttribute(Const.SESSION_RNUMBERS);
        session.removeAttribute("changeMenu");
        session.removeAttribute("DEPARTMENT_IDS");
        session.removeAttribute("DEPARTMENT_ID");
    }
}
